package org.example.authentication.shiro;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.example.authentication.pojo.SysPermissions;
import org.example.authentication.pojo.SysRole;
import org.example.authentication.pojo.SysUser;
import org.example.authentication.service.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

public class CustomRealm extends AuthorizingRealm {
    @Autowired
    private SysUserService sysUserService;

    /**
     * @MethodName doGetAuthorizationInfo
     * @Description 权限配置类，用于获取返回用户配置的角色和权限
     * @Param principalCollection
     * @Return AuthorizationInfo
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("执行doGetAuthorizationInfo");
        // 获取身份标识
        // getPrimaryPrincipal() 获取的是 doGetAuthenticationInfo() 返回对象 SimpleAuthenticationInfo 的身份标识 SimplePrincipalCollection 对象。
        String name = (String) principals.getPrimaryPrincipal();

        // 通过用户名获取角色权限集合
        SysUser user = sysUserService.listRolePermByName(name);
        // 添加角色和权限
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        for (SysRole role : user.getRoles()) {
            //添加角色
            simpleAuthorizationInfo.addRole(role.getRoleName());
            //添加权限
            for (SysPermissions permissions : role.getPermissions()) {
                simpleAuthorizationInfo.addStringPermission(permissions.getPermissionsName());
            }
        }
        return simpleAuthorizationInfo;
    }

    /**
     * @MethodName doGetAuthenticationInfo
     * @Description 认证配置类，用于获取返回用户的凭证信息（用户名、密码）
     * @Param authenticationToken
     * @Return AuthenticationInfo
     * @return
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行doGetAuthenticationInfo");
        if (StringUtils.isEmpty((String) authenticationToken.getPrincipal())) {
            return null;
        }
        // 获取用户信息
        String username = authenticationToken.getPrincipal().toString();
        String userPwd = new String((char[]) authenticationToken.getCredentials());
        System.out.println("传入需要认证的身份标识=" + username + ",凭证=" + userPwd);

        SysUser user = sysUserService.getOne(new QueryWrapper<SysUser>().eq("username", username));
//        SysUser user = sysUserService.getUser(username);
        if (user == null) {
            // 这里返回后会报出对应异常
            return null;
        } else {
            // SimpleAuthenticationInfo 是 Apache Shiro 中的一个核心类，用于封装认证信息。它主要用于在认证过程中传递用户的身份信息和凭证信息。
            // 查看源码，其实主要比对 credentials（凭证）。
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
                    user.getUsername(),  // 身份标识  封装成 SimplePrincipalCollection，传递给 doGetAuthorizationInfo() 方法
                    user.getPassword(),  // 凭证
                    getName()  // Realm 名称
            );
            return simpleAuthenticationInfo;
        }
    }
}
